home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_kernel_source / KERNEL / KMOD.C < prev    next >
C/C++ Source or Header  |  1999-09-17  |  3KB  |  134 lines

  1. /*
  2.     kmod, the new module loader (replaces kerneld)
  3.     Kirk Petersen
  4.  
  5.     Reorganized not to be a daemon by Adam Richter, with guidance
  6.     from Greg Zornetzer.
  7.  
  8.     Modified to avoid chroot and file sharing problems.
  9.     Mikael Pettersson
  10. */
  11.  
  12. #define __KERNEL_SYSCALLS__
  13.  
  14. #include <linux/sched.h>
  15. #include <linux/unistd.h>
  16. #include <linux/smp_lock.h>
  17.  
  18. #include <asm/uaccess.h>
  19.  
  20. /*
  21.     modprobe_path is set via /proc/sys.
  22. */
  23. char modprobe_path[256] = "/sbin/modprobe";
  24.  
  25. static inline void
  26. use_init_file_context(void)
  27. {
  28.     struct fs_struct * fs;
  29.  
  30.     lock_kernel();
  31.  
  32.     /*
  33.      * Don't use the user's root, use init's root instead.
  34.      * Note that we can use "init_task" (which is not actually
  35.      * the same as the user-level "init" process) because we
  36.      * started "init" with a CLONE_FS
  37.      */
  38.     exit_fs(current);    /* current->fs->count--; */
  39.     fs = init_task.fs;
  40.     current->fs = fs;
  41.     atomic_inc(&fs->count);
  42.  
  43.     unlock_kernel();
  44. }
  45.  
  46. static int exec_modprobe(void * module_name)
  47. {
  48.     static char * envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
  49.     char *argv[] = { modprobe_path, "-s", "-k", (char*)module_name, NULL };
  50.     int i;
  51.  
  52.     use_init_file_context();
  53.  
  54.     /* Prevent parent user process from sending signals to child.
  55.        Otherwise, if the modprobe program does not exist, it might
  56.        be possible to get a user defined signal handler to execute
  57.        as the super user right after the execve fails if you time
  58.        the signal just right.
  59.     */
  60.     spin_lock_irq(¤t->sigmask_lock);
  61.     flush_signals(current);
  62.     flush_signal_handlers(current);
  63.     spin_unlock_irq(¤t->sigmask_lock);
  64.  
  65.     for (i = 0; i < current->files->max_fds; i++ ) {
  66.         if (current->files->fd[i]) close(i);
  67.     }
  68.  
  69.     /* Drop the "current user" thing */
  70.     free_uid(current);
  71.  
  72.     /* Give kmod all privileges.. */
  73.     current->uid = current->euid = current->fsuid = 0;
  74.     cap_set_full(current->cap_inheritable);
  75.     cap_set_full(current->cap_effective);
  76.  
  77.     /* Allow execve args to be in kernel space. */
  78.     set_fs(KERNEL_DS);
  79.  
  80.     /* Go, go, go... */
  81.     if (execve(modprobe_path, argv, envp) < 0) {
  82.         printk(KERN_ERR
  83.                "kmod: failed to exec %s -s -k %s, errno = %d\n",
  84.                modprobe_path, (char*) module_name, errno);
  85.         return -errno;
  86.     }
  87.     return 0;
  88. }
  89.  
  90. /*
  91.     request_module: the function that everyone calls when they need
  92.     a module.
  93. */
  94. int request_module(const char * module_name)
  95. {
  96.     int pid;
  97.     int waitpid_result;
  98.     sigset_t tmpsig;
  99.  
  100.     /* Don't allow request_module() before the root fs is mounted!  */
  101.     if ( ! current->fs->root ) {
  102.         printk(KERN_ERR "request_module[%s]: Root fs not mounted\n",
  103.             module_name);
  104.         return -EPERM;
  105.     }
  106.  
  107.     pid = kernel_thread(exec_modprobe, (void*) module_name, CLONE_FS);
  108.     if (pid < 0) {
  109.         printk(KERN_ERR "request_module[%s]: fork failed, errno %d\n", module_name, -pid);
  110.         return pid;
  111.     }
  112.  
  113.     /* Block everything but SIGKILL/SIGSTOP */
  114.     spin_lock_irq(¤t->sigmask_lock);
  115.     tmpsig = current->blocked;
  116.     siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP));
  117.     recalc_sigpending(current);
  118.     spin_unlock_irq(¤t->sigmask_lock);
  119.  
  120.     waitpid_result = waitpid(pid, NULL, __WCLONE);
  121.  
  122.     /* Allow signals again.. */
  123.     spin_lock_irq(¤t->sigmask_lock);
  124.     current->blocked = tmpsig;
  125.     recalc_sigpending(current);
  126.     spin_unlock_irq(¤t->sigmask_lock);
  127.  
  128.     if (waitpid_result != pid) {
  129.         printk (KERN_ERR "kmod: waitpid(%d,NULL,0) failed, returning %d.\n",
  130.             pid, waitpid_result);
  131.     }
  132.     return 0;
  133. }
  134.